﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace CodePlex.Resourceful
{
    public class ClientRequest
    {
        private readonly string _method;
        private readonly string _path;
        private readonly NameValuePairs _headers;

        private Action<long> _bytesIn;
        private Action<long> _bytesOut;

        private bool _bufferOutput;

        private Stream _inputStream;


        protected ClientRequest(string method, string path, NameValuePairs headers, Stream inputStream)
        {
            _method = method;
            _path = path;
            _headers = headers ?? new NameValuePairs();
            _inputStream = inputStream;

            _bufferOutput = true;
        }

        public string Method
        {
            get
            {
                return _method;
            }
        }

        public string Path
        {
            get
            {
                return _path;
            }
        }

        public NameValuePairs Headers
        {
            get
            {
                return _headers;
            }
        }

        public Stream InputStream
        {
            get
            {
                return _inputStream;
            }
        }

        public Action<long> BytesIn
        {
            get
            {
                return _bytesIn;
            }
            set
            {
                _bytesIn = value;
            }
        }

        public Action<long> BytesOut
        {
            get
            {
                return _bytesOut;
            }
            set
            {
                _bytesOut = value;
            }
        }

        public bool BufferOutput
        {
            get
            {
                return _bufferOutput;
            }
            set
            {
                _bufferOutput = value;
            }
        }

        public static ClientRequest Create(string method, string path, NameValuePairs headers, Stream inputStream)
        {
            return new ClientRequest(method, path, headers, inputStream);
        }


    }


    public class GetRequest : ClientRequest
    {
        private GetRequest(string path, NameValuePairs headers)
            : base(HttpMethod.Get,path, headers, null)
        {
           
        }

        public static GetRequest Create(string path)
        {
            return new GetRequest(path,null);
        }

       
        public static GetRequest Create(string path, NameValuePairs parameters)
        {
            return GetRequest.Create(path, parameters, null);
        }

        public static GetRequest Create(string path, NameValuePairs parameters, NameValuePairs headers)
        {
            return new GetRequest(Utils.EncodeUrlPath(path, parameters), headers);
        }

        public static GetRequest Create(string path, string mediaType)
        {
            NameValuePairs headers = new NameValuePairs();
            headers[HttpHeader.Accept] = mediaType;
            return new GetRequest(path, headers);
        }

        public static GetRequest Create(string path, string mediaType, NameValuePairs parameters)
        {
            NameValuePairs headers = new NameValuePairs();
            headers[HttpHeader.Accept] = mediaType;
            return new GetRequest(Utils.EncodeUrlPath(path, parameters), headers);
        }

        public static GetRequest Create(string path, string mediaType, DateTime ifModifiedSince)
        {
            NameValuePairs headers = new NameValuePairs();
            headers[HttpHeader.IfModifiedSince] = Utils.ToHttpDate(ifModifiedSince);
            return new GetRequest(path, headers);
        }
    }

    public class DeleteRequest : ClientRequest
    {
        private DeleteRequest(string path, NameValuePairs headers)
            : base(HttpMethod.Delete, path, headers, null)
        {

        }

        public static DeleteRequest Create(string path)
        {
            return new DeleteRequest(path, null);
        }

        public static DeleteRequest Create(string path, NameValuePairs parameters)
        {
            return new DeleteRequest(Utils.EncodeUrlPath(path, parameters), null);
        }

    }


    public class HeadRequest : ClientRequest
    {
        private HeadRequest(string path, NameValuePairs headers)
            : base(HttpMethod.Head, path, headers, null)
        {

        }

        public static HeadRequest Create(string path)
        {
            return new HeadRequest(path, null);
        }

        public static HeadRequest Create(string path, NameValuePairs parameters)
        {
            return new HeadRequest(Utils.EncodeUrlPath(path, parameters), null);
        }

    }





    public class PostRequest : ClientRequest
    {
        private PostRequest(string path, NameValuePairs headers, Stream inputStream)
            : base(HttpMethod.Post, path, headers, inputStream)
        {
            
        }
        public static PostRequest Create(string path, NameValuePairs parameters, NameValuePairs headers, Stream inputStream)
        {
            return new PostRequest(Utils.EncodeUrlPath(path,parameters), headers, inputStream);
        }

        public static PostRequest Create(string path, string mediaType, NameValuePairs parameters)
        {
            return PostRequest.Create(path, mediaType, Utils.EncodeUrlPath(parameters));
        }

        public static PostRequest Create(string path, Stream representation)
        {
            return new PostRequest(path, null, representation);
        }
        public static PostRequest Create(string path, NameValuePairs headers, Stream representation)
        {
            return new PostRequest(path, headers, representation);
        }

        public static PostRequest Create(string path, string mediaType, string representation)
        {
            Stream input = new MemoryStream(Encoding.UTF8.GetBytes(representation));
            return PostRequest.Create(path, mediaType, input);
        }
        public static PostRequest Create(string path, string mediaType, Stream representation)
        {
            NameValuePairs headers = new NameValuePairs();
            headers[HttpHeader.ContentType] = mediaType;

            return PostRequest.Create(path, headers, representation);
        }

    }


    public class PutRequest : ClientRequest
    {
        private PutRequest(string path, NameValuePairs headers, Stream inputStream)
            : base(HttpMethod.Put, path, headers, inputStream)
        {

        }


        public static PutRequest Create(string path, NameValuePairs headers, Stream representation)
        {
            return new PutRequest(path, headers, representation);
        }

        public static PutRequest Create(string path, string mediaType, NameValuePairs parameters)
        {
            return PutRequest.Create(path, mediaType, Utils.EncodeUrlPath(parameters));
        }

        public static PutRequest Create(string path, string mediaType, string representation)
        {
            Stream input = new MemoryStream(Encoding.UTF8.GetBytes(representation));
            return PutRequest.Create(path, mediaType, input);
        }
        public static PutRequest Create(string path, string mediaType, Stream representation)
        {
            NameValuePairs headers = new NameValuePairs();
            headers[HttpHeader.ContentType] = mediaType;

            return new PutRequest(path, headers, representation);
        }


      
    }






}
